feat(claude): validate substitution tokens and record lifecycle contract - #347
Conversation
🦋 Changeset detectedLatest commit: a3cb102 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Post-merge CI root cause: the |
…the handshake queue (#368) - packages/agent-bundle/README.md: the Claude adapter no longer emits cwd for plugin-root stdio servers (#347 removed it because Claude's placeholder table excludes cwd); the README still claimed it did (#47). - docs/preview-packages.md: the --peerDeps rewrite now applies to the optional @agent-bundle/runtime peer declared by agent-bundle, not an agent-bundle peer inside the (renamed) runtime package (#45). - docs/framework-mode.md: restore the rendered-skills (SKILL.tsx) power tier and the skills precedence rule (AB4734/AB4735/AB4736, AB3003-AB3005) that #150's rewrite dropped from the RFC #63 newcomer doc. - runtime-client-surface-proxy.test.ts: unit-pin the #23 fix — host requests relayed during the App handshake are queued (bounded at 32) and flushed on ui/notifications/initialized instead of dropped; only the mcp-app-real e2e covered it before.
Summary
Slice 5 (final) of the #187 Claude parity pass: package/cache/data lifecycle contract, plus an honest substitution-token tightening.
packageLifecycleblock incapabilities/claude-2.1.250.jsonwith five rows and dated evidence:nodeDependencyInstall(unavailable) — pins the documented eligible-install contract:package.json+ Bun/npm lockfile, frozen installs with--ignore-scripts, 60-second limit, deterministic lockfile precedence (bun.lock→bun.lockb→npm-shrinkwrap.json→package-lock.json).yarnPnpmInstallAlternative(unavailable) — Yarn/pnpm lockfiles are documented as skipped (resolution-time hooks bypass--ignore-scripts); the${CLAUDE_PLUGIN_DATA}hook-install alternative is recorded.pluginCacheLifecycle(unavailable) — cache copy/link semantics, per-resolved-version directories, ~14-day orphan grace/sweep, symlink containment,path escapes plugin directoryrejection: all host install-time behavior.pluginPathSubstitution(degraded) — the closed documented substitution table (${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_DATA}/${CLAUDE_PROJECT_DIR}by component/field) is pinned and enforced for structured fields; Skill content and target-native hook documents remain opaque payloads.pluginDataLifecycle(unavailable) — last-scope-uninstall deletion and--keep-dataare host-owned.cwd: the adapter previously emittedcwd: "${CLAUDE_PLUGIN_ROOT}"as schema-valid future-proofing, but the placeholder table excludescwd, so the host would receive a literal unsubstituted string. Canonical plugin-root cwd is now omitted (absolute entry path + env anchor already carry the guarantee); token-bearing cwd values are rejected with the newclaude.substitution.token.unsupporteddiagnostic.extensionToLanguage,initializationOptions,settingsetc. previously passed through unexpanded; now rejected per the documented four-field table (command,args,env,workspaceFolder).package.json+package-lock.jsonwithout running any install (nonode_modulescreated), and accepts a skills entry symlinked outside the plugin root — proving lockfile handling and symlink containment are install-time, not validation-time.intersectCapabilityStates.Revisions
adapterRevision: claude1.18.0→1.19.0, unified plugin1.16.0→1.17.0(serialized after feat(claude): record agents-component parity evidence under G5 gate #346); capability sha re-pinned.Test plan
AGENT_BUNDLE_NATIVE_HOST_CONTRACTS=1): 412 tests, 0 failed, 0 skippedpnpm -w typecheckpnpm -w lintCloses the final open section of #187.